package com.gastudio.SMSimple;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

/**
 * Created by 余艾龙 on 2017/6/21.
 */
public class NormalDecoder implements ProtocolDecoder {
    private final AttributeKey CONTEXT=new AttributeKey(this.getClass(),"context");
    private final Charset charset;
    private int maxSMSLength=1024;

    public NormalDecoder() {
        this(Charset.defaultCharset());
    }
    public NormalDecoder(Charset charset) {
        this.charset=charset;
    }

    public Context getContext(IoSession session){
        Context ctx=(Context)session.getAttribute(CONTEXT);
        if(ctx==null){
            ctx=new Context();
            session.setAttribute(CONTEXT,ctx);
        }
        return ctx;
    }
    @Override
    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        final  int packHeadLength=(Integer.SIZE/8)+(Byte.SIZE/8);//定义包头长度
        Context ctx=this.getContext(session);
        ctx.append(in);
        IoBuffer buf=ctx.getBuf();
        buf.flip();
        while (buf.remaining()>=packHeadLength){
            buf.mark();
            int length=buf.getInt();
            byte flag=buf.get();
            if(length<0||length>maxSMSLength){
                buf.reset();
                break;
            }else if(length>=packHeadLength&&length-packHeadLength<=buf.remaining()){
                int oldLimit=buf.limit();
                buf.limit(buf.position()+length-packHeadLength);
                SmsObject SMS= (SmsObject) buf.getObject();
                buf.limit(oldLimit);
                ProtocolPack pack=new ProtocolPack(flag,SMS);
                out.write(pack);
            }else{
                buf.clear();
                break;
            }

        }
        if(buf.hasRemaining()){
            IoBuffer temp=IoBuffer.allocate(maxSMSLength).setAutoExpand(true);
            temp.put(buf);
            temp.flip();
            temp.reset();
            buf.put(temp);
        }else{
            buf.reset();
        }
    }

    @Override
    public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {

    }

    @Override
    public void dispose(IoSession session) throws Exception {

    }

    //内部类
    private class Context{
        public CharsetDecoder getDecoder() {
            return decoder;
        }

        public IoBuffer getBuf() {
            return buf;
        }

        public void setBuf(IoBuffer buf) {
            this.buf = buf;
        }

        private final CharsetDecoder decoder;
        private IoBuffer buf;
        private Context() {
            this.decoder = charset.newDecoder();
            buf=IoBuffer.allocate(80).setAutoExpand(true);
        }
        //最加上一次缓冲区的数据
        public void append(IoBuffer inBuf){
            this.getBuf().put(inBuf);
        }

        public void reset(){
            decoder.reset();
        }
    }

    public int getMaxSMSLength() {
        return maxSMSLength;
    }

    public void setMaxSMSLength(int maxPackLength) {
        if(maxPackLength<0){
            throw new IllegalArgumentException("maxPackLength参数错误："+maxPackLength);
        }
        this.maxSMSLength = maxPackLength;
    }
}
